﻿using System;
using System.Collections.Generic;

namespace SystemWnioskujacy
{
    public static class Base
    {
        public class Probabilities
        {
            public double grf;
            public double irf;

            public Probabilities()
            {
                this.grf = 1.0;
                this.irf = 1.0;
            }

            public Probabilities(double grf, double irf)
            {
                this.grf = grf;
                this.irf = irf;
            }
        }

        public static readonly GraphBase FactsBase = new GraphBase();
        public static readonly Rules RulesBase = new Rules();
        public static Dictionary<int, Probabilities> Ps = new Dictionary<int, Probabilities>();

        public static void Add(string Fact)
        {
            int ID;
            if (FactsBase.Add(Fact, out ID)) Ps[ID] = new Probabilities();
        }

        public static void Add(string Fact, double grf, double irf)
        {
            int ID;
            if (FactsBase.Add(Fact, out ID)) Ps[ID] = new Probabilities(grf, irf);
            else
            {
                if (ID >= Base.RulesBase.min_id)
                {
                    double n_grf = 0.0, n_irf = 0.0;

                    n_grf = Math.Max(Ps[ID].grf, grf);
                    n_irf = (1 - 1 / (Base.RulesBase.t + 1)) * Ps[ID].irf + (1 / (Base.RulesBase.t + 1)) * irf;

                    Ps[ID] = new Probabilities(n_grf, n_irf);
                }
            }
        }

        public static void Remove(string Fact)
        {
            int ID;
            if (FactsBase.Remove(Fact, out ID)) Ps.Remove(ID);
        }

        public static void Remove(int ID)
        {
            if (FactsBase.Remove(ID)) Ps.Remove(ID);
        }

        public static void Clear()
        {
            FactsBase.Clear();
            RulesBase.Clear();
        }

        public static double Get_GRF(int ID)
        {
            if (ID > -1 && FactsBase.Exists(ID))
            {
                Probabilities P = Ps[ID];
                return P.grf;
            }
            else return 2.0;
        }

        public static double Get_GRF(String fact)
        {
            int ID = FactsBase.GetID(fact);
            if (ID > -1)
            {
                Probabilities P = Ps[ID];
                return P.grf;
            }
            else return 2.0;
        }

        public static double Get_IRF(int ID)
        {
            if (ID > -1 && FactsBase.Exists(ID))
            {
                Probabilities P = Ps[ID];
                return P.irf;
            }
            else return 2.0;
        }

        public static double Get_IRF(String fact)
        {
            int ID = FactsBase.GetID(fact);
            if (ID > -1)
            {
                Probabilities P = Ps[ID];
                return P.irf;
            }
            else return 2.0;
        }

        public static void Add_R1()
        {
            Queries Qs = new Queries();
            Query Q1 = new Query();
            Query Q2 = new Query();
            QueryParameter P1 = new QueryParameter("Wydz_Rodz");
            QueryParameter P2 = new QueryParameter(new string[] { "WInf_st", "WEl_st" });

            QueryParameter P3 = new QueryParameter("Kier");
            QueryParameter P4 = new QueryParameter("Inf_st");

            Q1.Add(P1);
            Q1.Add(P2);

            Q2.Add(P3);
            Q2.Add(P4);

            Qs.Add(Q1);

            Functions Fs = new Functions();

            Rule R = new Rule(Qs, Fs, 0.75, 0.55);
            RulesBase.Add(R);
            Fs.Add(() => Function.Assert(Q2, R));
        }

        public static void Add_R2()
        {
            Queries Qs = new Queries();
            Query Q1 = new Query();
            Query Q2 = new Query();
            QueryParameter P1 = new QueryParameter("Wydz_Rodz");
            QueryParameter P2 = new QueryParameter("WInf_st");

            QueryParameter P3 = new QueryParameter("Kier");
            QueryParameter P4 = new QueryParameter("Inf_st");

            Q1.Add(P1);
            Q1.Add(P2);

            Q2.Add(P3);
            Q2.Add(P4);

            Qs.Add(Q1);

            Functions Fs = new Functions();

            Rule R = new Rule(Qs, Fs, 0.9, 0.8);
            RulesBase.Add(R);
            Fs.Add(() => Function.Assert(Q2, R));
        }

        public static void Add_R3()
        {
            Queries Qs = new Queries();
            Query Q1 = new Query();
            Query Q2 = new Query();
            QueryParameter P1 = new QueryParameter("Kier");
            QueryParameter P2 = new QueryParameter("Inf_st");

            QueryParameter P3 = new QueryParameter("Sprzet");
            QueryParameter P4 = new QueryParameter(new string[] { "K_st", "Lap" });

            Q1.Add(P1);
            Q1.Add(P2);

            Q2.Add(P3);
            Q2.Add(P4);

            Qs.Add(Q1);

            Functions Fs = new Functions();

            Rule R = new Rule(Qs, Fs, 0.7, 0.6);
            RulesBase.Add(R);
            Fs.Add(() => Function.Assert(Q2, R));
        }

        public static void Add_R4()
        {
            Queries Qs = new Queries();
            Query Q1 = new Query();
            Query Q2 = new Query();
            Query Q3 = new Query();
            QueryParameter P1 = new QueryParameter("Kier");
            QueryParameter P2 = new QueryParameter("Inf_st");

            QueryParameter P3 = new QueryParameter("Rok");
            QueryParameter P4 = new QueryParameter(new string[] { "1", "2" });

            QueryParameter P5 = new QueryParameter("Sprzet");
            QueryParameter P6 = new QueryParameter(new string[] { "K_st", "Lap" });

            Q1.Add(P1);
            Q1.Add(P2);

            Q2.Add(P3);
            Q2.Add(P4);

            Q3.Add(P5);
            Q3.Add(P6);

            Qs.Add(Q1);
            Qs.Add(Q2);

            Functions Fs = new Functions();

            Rule R = new Rule(Qs, Fs, 0.9, 0.8);
            RulesBase.Add(R);
            Fs.Add(() => Function.Assert(Q3, R));
        }

        public static void Add_R5()
        {
            Queries Qs = new Queries();
            Query Q1 = new Query();
            Query Q2 = new Query();
            Query Q3 = new Query();
            Query Q4 = new Query();
            QueryParameter P1 = new QueryParameter("Kier");
            QueryParameter P2 = new QueryParameter("Inf_st");

            QueryParameter P3 = new QueryParameter("Rok");
            QueryParameter P4 = new QueryParameter(new string[] { "1", "2" });

            QueryParameter P5 = new QueryParameter("Plec");
            QueryParameter P6 = new QueryParameter("K");

            QueryParameter P7 = new QueryParameter("Sprzet");
            QueryParameter P8 = new QueryParameter(new string[] { "K_st", "Lap" });

            Q1.Add(P1);
            Q1.Add(P2);

            Q2.Add(P3);
            Q2.Add(P4);

            Q3.Add(P5);
            Q3.Add(P6);

            Q4.Add(P7);
            Q4.Add(P8);

            Qs.Add(Q1);
            Qs.Add(Q2);
            Qs.Add(Q3);

            Functions Fs = new Functions();

            Rule R = new Rule(Qs, Fs, 0.85, 0.85);
            RulesBase.Add(R);
            Fs.Add(() => Function.Assert(Q4, R));
        }

        public static void Test()
        {
            RulesBase.r1 = 0.7;
            RulesBase.r2 = 0.7;
            RulesBase.t = 1.8;

            Base.Add("Wydz_Rodz WInf_st", 1.0, 1.0);
            Base.Add("Rok 1", 0.95, 0.0);
            Base.Add("Rok 2", 0.95, 0.0);

            Add_R1();
            Add_R2();
            Add_R3();
            Add_R4();
            Add_R5();

            Function.Facts();
            Function.Rules();
            RulesBase.Run2();
            Function.Facts();
        }

        public static void Test2()
        {
            ///*
            Base.Add("parent Elżbieta Paweł");
            Base.Add("parent Elżbieta Paweł");
            Base.Add("parent Elżbieta Monika");
            Base.Add("parent Tomasz Paweł");
            Base.Add("parent Tomasz Monika");
            Base.Add("parent Ludomiła Elżbieta");
            Base.Add("parent Tadeusz Tomasz");
            Base.Add("parent Barbara Tomasz");

            Base.Add("parent Zbigniew Zbysław");
            Base.Add("parent Zbysław Zygmunt");
            Base.Add("parent Zygmunt Zawieja");
            Base.Add("parent Zawieja Złodzirej");
            Base.Add("parent Złodzirej Zmysław");
            //*/
            Queries Qs = new Queries();
            Query Q1 = new Query();
            Query Q2 = new Query();
            Query Q3 = new Query();
            QueryParameter P1 = new QueryParameter("parent");
            QueryParameter P2 = new QueryParameter("?x", new string[0]);
            QueryParameter P3 = new QueryParameter("?y", new string[0]);
            QueryParameter P4 = new QueryParameter("?z", new string[0]);
            QueryParameter P5 = new QueryParameter("grandparent"); // defrule XXX ((parent ?x ?y) (parent ?y ?z) => assert(grandparent ?x ?z)
            Q1.Add(P1);
            Q1.Add(P2);
            Q1.Add(P3);
            Q2.Add(P1);
            Q2.Add(P3);
            Q2.Add(P4);
            Q3.Add(P5);
            Q3.Add(P2);
            //Q3.Add(P3);
            Q3.Add(P4);
            Qs.Add(Q1);
            Qs.Add(Q2);
            Functions Fs = new Functions();
            Rule R = new Rule(Qs, Fs);
            RulesBase.Add(R);
            Fs.Add(() => Function.Assert(Q3, R));
            ///*
            RulesBase.Run();

            //string[] A = FactBase.Execute(Q1);
            Function.Facts();
            // */
        }
    }
}
